package cn.zucc.edu.bruce.iot;

import android.content.SharedPreferences;
import android.os.Bundle;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;

import cn.zucc.edu.bruce.iot.receiver.ReceiveIOTData;
import cn.zucc.edu.bruce.iot.receiver.ReceiveInfraredData;
import cn.zucc.edu.bruce.iot.receiver.ReceiveMotorData;
import cn.zucc.edu.bruce.iot.receiver.ReceiveRgbData;
import cn.zucc.edu.bruce.iot.receiver.ReceiveTemperHumData;
import cn.zucc.edu.bruce.iot.send.SendDecData;
import cn.zucc.edu.bruce.iot.send.SendIOTData;

public class ScrollingActivity extends AppCompatActivity {
    public TextView tvDevNum, tvSno, tvHeart, tvSensorNum, tvTem, tvHum, tvR, tvG, tvB, tvMotor;
    private EditText edtR, edtG, edtB, edtMotor;
    private ImageView imageInfrared;
    private Button btSend;
    private TextView textChecksum;
    private FloatingActionButton fab;
    private SocketServer server;
    private SharedPreferences pref;
    private int port;
    public MyHandler myHandler;
    public SendIOTData sendIOTData;
    private ReceiveMotorData motorData;
    private ReceiveRgbData rgbData;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scrolling);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        myHandler = new MyHandler();
        //读取保存的端口号
        pref = getSharedPreferences("iot", MODE_PRIVATE);

        fab = findViewById(R.id.fab);

        imageInfrared = findViewById(R.id.image_infrared);

        textChecksum = findViewById(R.id.text_checksum2);
        tvDevNum = findViewById(R.id.text_device_num);
        tvSensorNum = findViewById(R.id.text_sensor_num);
        tvSno = findViewById(R.id.text_sno);
        tvHeart = findViewById(R.id.text_heartbeat);
        tvTem = findViewById(R.id.text_temperature);
        tvHum = findViewById(R.id.text_humidity);
        tvR = findViewById(R.id.text_r);
        tvG = findViewById(R.id.text_g);
        tvB = findViewById(R.id.text_b);
        tvMotor = findViewById(R.id.text_motor);

        edtR = findViewById(R.id.edt_r);
        edtG = findViewById(R.id.edt_g);
        edtB = findViewById(R.id.edt_b);
        edtMotor = findViewById(R.id.edt_motor);

        //初始化显示数据
        init();

        fab.setOnClickListener(view -> {
            if (server == null || SocketServer.getSst().isClosed()) {
                startServer();
                fab.setImageResource(R.drawable.ic_stop_black_24dp);
                Snackbar.make(view, "Socket 服务开启，端口号为:" + port, Snackbar.LENGTH_LONG).setAction("取消", v -> {
                    stopServer();
                    fab.setImageResource(R.drawable.ic_play_arrow_black_24dp);
                    Toast.makeText(ScrollingActivity.this, "你取消了启动", Toast.LENGTH_SHORT).show();
                }).show();
            } else {
                stopServer();
                fab.setImageResource(R.drawable.ic_play_arrow_black_24dp);
                Snackbar.make(view, "Socket 服务关闭" + port, Snackbar.LENGTH_LONG).show();
            }
        });

        btSend = findViewById(R.id.bt_send);
        btSend.setOnClickListener(v -> {
            int motor;
            int r, g, b;
            //获得输入数据并发送
            try {
                motor = Integer.parseInt(edtMotor.getText().toString());
                if (motor > 10000) throw new NumberException("电机不能超过10000");
                if (motor < 0) throw new NumberException("电机不能低于0");
                r = Integer.parseInt(edtR.getText().toString());
                g = Integer.parseInt(edtG.getText().toString());
                b = Integer.parseInt(edtB.getText().toString());
                if (r > 255 || r < 0 || g > 255 || g < 0 || b > 255 || b < 0)
                    throw new NumberException("RGB范围必须在0~255");
                if (sendIOTData == null) {
                    sendIOTData = new SendIOTData();
                    SendDecData sendDecData1 = new SendDecData(0);
                    sendDecData1.setNumber1(motor);

                    SendDecData sendDecData2 = new SendDecData(1);
                    sendDecData2.setNumber1(r);
                    sendDecData2.setNumber2(g);
                    sendDecData2.setNumber3(b);
                    sendIOTData.getSendDecData().add(sendDecData1);
                    sendIOTData.getSendDecData().add(sendDecData2);
                } else {
                    sendIOTData.getSendDecData().get(0).setNumber1(motor);
                    sendIOTData.getSendDecData().get(1).setNumber1(r);
                    sendIOTData.getSendDecData().get(1).setNumber2(g);
                    sendIOTData.getSendDecData().get(1).setNumber3(b);
                }
            } catch (NumberFormatException e) {
                new AlertDialog.Builder(ScrollingActivity.this).setTitle("提示")
                        .setMessage("输入格式有误")
                        .setPositiveButton("确定", null)
                        .show();
            } catch (NumberException e) {
                new AlertDialog.Builder(ScrollingActivity.this).setTitle("提示")
                        .setMessage(e.getErr())
                        .setPositiveButton("确定", null)
                        .show();
            }
        });
    }

    private void init() {
        motorData = new ReceiveMotorData(1);
        rgbData = new ReceiveRgbData(-1, -1, -1);

        edtMotor.setText(String.valueOf(1));
        edtR.setText(String.valueOf(-1));
        edtG.setText(String.valueOf(-1));
        edtB.setText(String.valueOf(-1));
    }

    private void startServer() {
        port = Integer.parseInt(pref.getString("port", ""));
        server = new SocketServer(port, ScrollingActivity.this);
        server.start();
        SocketServer.isContinue = true;
    }

    private void stopServer() {
        try {
            SocketServer.getSst().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        SocketServer.isContinue = false;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_scrolling, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_quit:
                finish();
                break;
            case R.id.action_settings:
                CustomDialog customDialog = new CustomDialog(ScrollingActivity.this);
                customDialog.show();
                break;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    class MyHandler extends Handler {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case 1:
                    ReceiveIOTData receiveIOTData = (ReceiveIOTData) msg.getData().getSerializable("receive");
                    if (receiveIOTData != null) {
                        tvSno.setText("学号: " + receiveIOTData.getSno());
                        tvDevNum.setText("设备号: " + (int) receiveIOTData.getIotId());
                        tvSensorNum.setText("传感器数: " + receiveIOTData.getSensorNum());
                        tvHeart.setText("心跳: " + receiveIOTData.getHeartbeat());
                    }

                    ReceiveTemperHumData receiveTemperHumData = (ReceiveTemperHumData) receiveIOTData.getReceiveSensorData().get(0);
                    tvTem.setText("温度:  " + receiveTemperHumData.getTemperature());
                    tvHum.setText("湿度:  " + receiveTemperHumData.getHumidity());

                    ReceiveRgbData receiveRgbData = (ReceiveRgbData) receiveIOTData.getReceiveSensorData().get(1);
                    if (receiveRgbData.getRed() != rgbData.getRed()) {
                        edtR.setText(String.valueOf(receiveRgbData.getRed()));
                        rgbData.setRed(receiveRgbData.getRed());
                    }
                    if (receiveRgbData.getGreen() != rgbData.getGreen()) {
                        edtG.setText(String.valueOf(receiveRgbData.getGreen()));
                        rgbData.setGreen(receiveRgbData.getGreen());
                    }
                    if (receiveRgbData.getBlue() != rgbData.getBlue()) {
                        edtB.setText(String.valueOf(receiveRgbData.getBlue()));
                        rgbData.setBlue(receiveRgbData.getBlue());
                    }

                    ReceiveInfraredData receiveInfraredData = (ReceiveInfraredData) receiveIOTData.getReceiveSensorData().get(2);
                    if (receiveInfraredData.isOpen())
                        imageInfrared.setImageResource(R.drawable.ic_infrared_close);
                    else
                        imageInfrared.setImageResource(R.drawable.ic_infrared_open);

                    ReceiveMotorData receiveMotorData = (ReceiveMotorData) receiveIOTData.getReceiveSensorData().get(3);
                    if (receiveMotorData.getSpeed() != motorData.getSpeed()) {
                        edtMotor.setText(String.valueOf(receiveMotorData.getSpeed()));
                        motorData.setSpeed(receiveMotorData.getSpeed());
                    }
                    textChecksum.setText("0X" + Integer.toHexString(receiveIOTData.getChecksum()));
                    break;
                default:
                    break;
            }
        }
    }

    class NumberException extends RuntimeException {
        private String err;

        NumberException(String err) {
            this.err = err;
        }

        public String getErr() {
            return err;
        }
    }
}
